package elems;

import common.ParseException;
import common.Strings;

import java.util.ArrayList;

public class Clazz extends ClassElem {
    private int parentBodySshift, bodyShift;
    private ArrayList<Selector> selectors;
    private AnchorDefine anchor;
    private ArrayList<ClassElem> elems;

    public Clazz(Clazz parent, int parentBodySshift) {
        super(parent);
        this.parentBodySshift = parentBodySshift;
        bodyShift = -1;
        selectors = new ArrayList<Selector>();
        elems = new ArrayList<ClassElem>();
    }

    public void addString(int lineNum, String inpStr, String nextStr) throws ParseException {
        int shift = Strings.getSpaceShift(inpStr);
        if (shift > parentBodySshift && bodyShift == -1)
            bodyShift = shift;

        if (shift == parentBodySshift) {
            if (nextStr != null) {
                // Тут мы добавляем селекторы и анкоры в заголовок этого класса
                ArrayList<Selector> selectors = Selector.get(this, lineNum, inpStr);
                if (selectors != null) {
                    if (anchor == null) {
                        this.selectors.addAll(selectors);
                        //---------------=======================[DEBUG OUT]=======================---------------//
                        for (Selector selector : selectors)
                            System.out.println(Strings.getSpaceShift(shift) + selector.getCss());
                    } else
                        throw new ParseException("Нельзя добавлять селекторы после определения анкора (Строка " + lineNum + ")");
                    return;
                }
                AnchorDefine anchorDefine = AnchorDefine.get(this, lineNum, inpStr, nextStr);
                if (anchorDefine != null) {
                    if (anchor == null) {
                        anchor = anchorDefine;
                        //---------------=======================[DEBUG OUT]=======================---------------//
                        anchor.print(parentBodySshift);
                    } else
                        throw new ParseException("Повторное определение анкора (Строка " + lineNum + ")");
                    return;
                }
                throw new ParseException("Здесь нас быть не должно 'shift == parentBodySshift' (Строка " + lineNum + ")");
            }
        } else if (shift == bodyShift) {
            if (Selector.is(lineNum, inpStr) || nextStr != null && AnchorDefine.is(lineNum, inpStr, nextStr)) {
                // Тут мы можем добавить заголовки к новым вложенным классам
                if (elems.size() == 0 || //Если в списке никого нет
                        !(elems.get(elems.size() - 1) instanceof Clazz) || // если последний эл-т в списке не класс
                        (elems.get(elems.size() - 1) instanceof Clazz) && ((Clazz) elems.get(elems.size() - 1)).isBodyExpected()) // если последний элемент класс, но у него уже есть тело, а т.к. уже идет тело, то селектрора там быть не может - нужен новы йкласс
                    elems.add(new Clazz(this, bodyShift)); // Добавляем в конец новый класс
                ((Clazz) elems.get(elems.size() - 1)).addString(lineNum, inpStr, nextStr);
            } else {
                // Или добавить свойства к этому классу


                ClassElem elem = null;
                if ((elem = Empty.get(lineNum, inpStr)) != null)
                    elems.add(elem);
                else if ((elem = Comment.get(lineNum, inpStr)) != null)
                    elems.add(elem);
                else if ((elem = Var.get(this, lineNum, inpStr)) != null)
                    elems.add(elem);
                else if ((elem = Anchor.get(this, lineNum, inpStr)) != null){
                    if(getParent()==null)
                        throw new ParseException("Строка "+lineNum+" распознана как вызов анкора. Строки данного типа в корневом классе недопустимы");
                    elems.add(elem);
                }

                if (elem != null)
                    elems.get(elems.size() - 1).print(shift);
                else
                    throw new ParseException("Строка "+lineNum+" никак не распознана");
            }
        } else if (shift > bodyShift) {
            // Добавляем строки к вложенным классам
            if (!(elems.get(elems.size() - 1) instanceof Clazz))
                throw new ParseException("Попытка добавить вложенное свойство в теле элемента не являющегося классом (Строка " + lineNum + ")");
            ((Clazz) ((Clazz) elems.get(elems.size() - 1))).addString(lineNum, inpStr, nextStr);
        } else
            throw new ParseException("Этой ошибки быть не должно. parentBodyShift:" + parentBodySshift + " bodyShift:" + bodyShift + " shift:" + shift + " (Строка " + lineNum + ")");
    }

    public void print(int shift) {
        for (Selector selector : selectors)
            System.out.println(Strings.getSpaceShift(shift) + selector.getCss());
        if (anchor != null)
            anchor.print(shift);
        for (ClassElem elem : elems)
            elem.print(shift + 1);
    }

    public boolean isBodyExpected() {
        return elems.size() > 0;
    }

    public boolean isHasSelectors(){
        return selectors.size()>0;
    }
}
